package com.sweet.io.file;

import com.sweet.collection.CollectionUtil;
import com.sweet.enums.Charset;
import com.sweet.lang.ArrayUtil;
import com.sweet.lang.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.Charsets;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;

import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 文件工具类
 *
 * @author limi
 * @version 2015-10-15
 */
@Slf4j
public final class FileUtil {
    private FileUtil() {
    }

    /**
     * 获取文件名，来自spring<br/>
     * Extract the filename from the given path, e.g.
     * {@code "mypath/myfile.txt" -> "myfile.txt"}.
     *
     * @param path the file path (may be {@code null})
     * @return the extracted filename, or {@code null} if none
     */
    public static String getFilename(String path) {
        if (path == null) {
            return null;
        }

        int separatorIndex = path.lastIndexOf("/");
        if (separatorIndex == -1) {
            separatorIndex = path.lastIndexOf("\\");
        }
        return (separatorIndex != -1 ? path.substring(separatorIndex + 1) : path);
    }

    /**
     * 获取文件后缀
     *
     * @param fileName 文件名
     * @return
     */
    public static String getFileSuffix(String fileName) {
        if (fileName.lastIndexOf(".") == -1) {
            return "";
        }

        return fileName.substring(fileName.lastIndexOf("."), fileName.length());
    }

    /**
     * 清理路径
     *
     * @param path
     * @return
     */
    public static String clearPath(String path) {
        return path == null ? null : StringUtils.replace(path, "\\", "/");
    }

    /**
     * 定义csv文件
     *
     * @param fileName 文件绝对路径，c:/myproject/down/a.csv
     * @param titles   文件标题
     * @param datas    文件内容
     * @return
     */
    public static void createCSV(String fileName, String[] titles, List<String[]> datas) {
        StringBuilder fileBuff = new StringBuilder();

        // 定义标题
        if (ArrayUtil.isNotEmpty(titles)) {
            for (String title : titles) {
                fileBuff.append(title).append(",");
            }
            fileBuff.append("\r");
        }

        // 定义内容
        if (CollectionUtil.isNotEmpty(datas)) {
            for (String[] oneData : datas) {
                if (oneData != null && oneData.length > 0) {
                    for (String temp : oneData) {
                        fileBuff.append(temp).append(",");
                    }
                    fileBuff.append("\r");
                }
            }
        }

        // 生成文件
        createCsv(fileName, fileBuff.toString());
    }

    /**
     * 生成Text文件
     *
     * @param fileUrl
     * @param data
     */
    public static void createText(String fileUrl, String data) {
        write(fileUrl, null, data, false);
    }

    /**
     * Text文件追加
     *
     * @param fileUrl
     * @param data
     */
    public static void appendText(String fileUrl, String data) {
        write(fileUrl, null, data, true);
    }

    /**
     * 生成CSV文件
     *
     * @param fileUrl
     * @param data
     */
    public static void createCsv(String fileUrl, String data) {
        write(fileUrl, new byte[]{(byte) 0xEF, (byte) 0xBB, (byte) 0xBF}, data, false);
    }

    /**
     * csv文件追加
     *
     * @param fileUrl
     * @param data
     */
    public static void appendCSV(String fileUrl, String data) {
        write(fileUrl, new byte[]{(byte) 0xEF, (byte) 0xBB, (byte) 0xBF}, data, true);
    }

    /**
     * 生成文件
     *
     * @param fileUrl
     * @param prefixs 前缀数据，一般用于编写bom
     * @param data
     * @return
     */
    private static boolean write(String fileUrl, byte[] prefixs, String data, boolean append) {
        // 数据预处理
        if (data == null) {
            data = "";
        }

        File file = new File(fileUrl);
        if (!file.exists()) {
            File parent = file.getParentFile();
            if (parent != null) {
                parent.mkdirs();
            }
        }

        // 编写无bom文件
        if (prefixs == null || prefixs.length == 0) {
            return writeStringToFile(file, data, Charset.UTF8, append);
        }

        // 编写含bom文件
        OutputStream out = null;
        try {
            out = FileUtils.openOutputStream(file, append);
            out.write(prefixs);
            out.write(data.getBytes(Charsets.toCharset(Charset.UTF8.getCharset())));
            out.close();
            return true;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        } finally {
            try {
                if (out != null) {
                    out.close();
                }
            } catch (IOException ioe) {
                ioe.printStackTrace();
            }
        }
    }

    /**
     * 写文件
     *
     * @param file
     * @param data
     * @param charset
     * @param append
     * @throws IOException
     */
    public static boolean writeStringToFile(File file, String data, Charset charset, boolean append) {
        try {
            FileUtils.writeStringToFile(file, data, charset.getCharset(), append);
            return true;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 读文件
     *
     * @param file
     * @param charset
     * @return
     */
    public static String readFileToString(File file, Charset charset) {
        try {
            return FileUtils.readFileToString(file, charset.getCharset());
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 获取符合后缀条件的文件
     *
     * @param root        检查的根目录，可能有嵌套目录，需要递归。支持为单个文件
     * @param startModify 文件开始修改日期，可选，null表示不限制，非null表示从该时间起，文件有修改则处理
     * @param suffixs     后缀列表，如.js，.txt
     */
    public static List<File> getSuffixFiles(String root, Date startModify, String... suffixs) {
        //定义目录，去掉多余后缀
        if (root.endsWith("/")) {
            root = StringUtil.deleteSuffix(root, "/");
        }
        if (root.endsWith("\\")) {
            root = StringUtil.deleteSuffix(root, "\\");
        }

        //定义文件目录
        File rootFile = new File(root);
        if (!rootFile.exists()) {
            return null;
        }

        //获取所有文件
        File[] files;
        if (rootFile.isDirectory()) {
            //获取目录下所有文件
            files = rootFile.listFiles();
        } else {
            //若是文件，则直接采用
            files = new File[]{rootFile};
        }

        //验证文件有效性
        if (ArrayUtil.isEmpty(files)) {
            //System.out.println("目录[" + dir + "]下无文件!");
            return null;
        }

        //获取检测的文件修改时间
        long startTime = startModify == null ? 0 : startModify.getTime();

        //JS文件列表
        List<File> tempFiles;
        List<File> suffixFiles = new ArrayList<>();
        for (File file : files) {
            if (file.isDirectory()) {
                //若当前文件为目录，则继续递归
                tempFiles = getSuffixFiles(file.getAbsolutePath(), startModify, suffixs);
                if (CollectionUtil.isNotEmpty(tempFiles)) {
                    suffixFiles.addAll(tempFiles);
                }
            } else {
                //优先判断最后修改时间
                if (startTime > file.lastModified()) {
                    continue;
                }

                //验证有效后缀
                for (String suffix : suffixs) {
                    if (file.getName().endsWith(suffix)) {
                        suffixFiles.add(file);
                    }
                }
            }
        }

        return suffixFiles;
    }
}